﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VerbrauchProcessor.DatabaseAccess.DataModel
{
	public class MeasurementIntervall
	{
		#region Fields

		/// <summary>
		/// Start gas value of intervall;
		/// </summary>
		decimal mGasStart;
		
		/// <summary>
		/// End gas value of intervall;
		/// </summary>
		decimal mGasEnd;

		/// <summary>
		/// Start gas value of intervall;
		/// </summary>
		decimal mWaterStart;

		/// <summary>
		/// End gas value of intervall;
		/// </summary>
		decimal mWaterEnd;

		/// <summary>
		/// Start gas value of intervall;
		/// </summary>
		decimal mElectricEnergyStart;

		/// <summary>
		/// End gas value of intervall;
		/// </summary>
		decimal mElectricEnergyEnd;
		
		#endregion

		#region Properties

		/// <summary>
		/// Start time of intervall.
		/// </summary>
		public DateTime StartDate{get;set;}

		/// <summary>
		/// End time of intervall.
		/// </summary>
		public DateTime EndDate { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		public decimal GasPerDay_m3 { get; private set; }
		
		/// <summary>
		/// 
		/// </summary>
		public decimal WaterPerDay_m3 { get; private set; }
		
		/// <summary>
		/// 
		/// </summary>
		public decimal ElectricityPerDay_kwh { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		public int TimeIntervall_d { get; private set;}

		#endregion

		#region  Constructors
		
		/// <summary>
		/// Constructor of a measurement intervall.
		/// </summary>
		/// <param name="firstSample"></param>
		/// <param name="secondSample"></param>
		public MeasurementIntervall(Sample firstSample, Sample secondSample)
		{

			StartDate = firstSample.Date;
			EndDate   = secondSample.Date;

			mGasStart = firstSample.Gas_m3;
			mGasEnd = secondSample.Gas_m3;

			mWaterStart = firstSample.Water_m3;
			mWaterEnd = secondSample.Water_m3;

			mElectricEnergyStart = firstSample.ElectricEnergy_kwh;
			mElectricEnergyEnd = secondSample.ElectricEnergy_kwh;


			if (secondSample.Date.DayOfYear > firstSample.Date.DayOfYear)
			{
				TimeIntervall_d = secondSample.Date.DayOfYear - firstSample.Date.DayOfYear;
			}
			else
			{
				// this should only be the case for samples between years 
				if (secondSample.Date.Year > firstSample.Date.Year)
				{
					TimeIntervall_d = (secondSample.Date.DayOfYear + 365) - firstSample.Date.DayOfYear;
				}
				else 
				{
					throw new Exception("Date timestamps are invalid.");
				}
			}

			if (secondSample.ElectricEnergy_kwh >= firstSample.ElectricEnergy_kwh)
			{
				ElectricityPerDay_kwh = (secondSample.ElectricEnergy_kwh - firstSample.ElectricEnergy_kwh) / TimeIntervall_d;
			}
			else 
			{
				//in case the electric counter was replaced by a newer one.
				ElectricityPerDay_kwh = (secondSample.ElectricEnergy_kwh ) / TimeIntervall_d;
			}

			if (secondSample.Water_m3 >= firstSample.Water_m3)
			{
				WaterPerDay_m3 = (secondSample.Water_m3 - firstSample.Water_m3) / TimeIntervall_d;
			}
			else
			{
				//in case the water counter was replaced by a newer one.
				WaterPerDay_m3 = secondSample.Water_m3 / TimeIntervall_d;
			}

			if (secondSample.Gas_m3 >= firstSample.Gas_m3)
			{
				GasPerDay_m3 = (secondSample.Gas_m3 - firstSample.Gas_m3) / TimeIntervall_d;
			}
			else 
			{
				//in case the gas counter was replaced by a newer one.
				GasPerDay_m3 = secondSample.Gas_m3 / TimeIntervall_d;
			}
		} 

		/// <summary>
		/// 
		/// </summary>
		/// <param name="firstSample"></param>
		/// <param name="secondSample"></param>
		public MeasurementIntervall(MeasurementIntervall mi)
		{
			this.StartDate = mi.StartDate;
			this.EndDate = mi.StartDate;

			this.GasPerDay_m3 = mi.GasPerDay_m3;
			this.WaterPerDay_m3 = mi.WaterPerDay_m3;
			this.ElectricityPerDay_kwh = mi.ElectricityPerDay_kwh;
			this.TimeIntervall_d = mi.TimeIntervall_d;
		}

		#endregion

		#region Helper Function
		
		/// <summary>
		/// Creates an intervall for every day between the intervall. 
		/// </summary>
		/// <param name="mi">Intervall to extend.</param>
		public static IList<MeasurementIntervall> extendData(MeasurementIntervall mi)
		{
			IList<MeasurementIntervall> list = new List<MeasurementIntervall>();
			
			int diffDays = mi.EndDate.DayOfYear - mi.StartDate.DayOfYear;
			
			for (int i = 0; i < diffDays; i++)
			{ 
				MeasurementIntervall mei = new MeasurementIntervall(mi);
				mei.StartDate = mi.StartDate.AddDays(i);
				mei.EndDate = mei.StartDate;

				list.Add(mei);
			}

			return list;
		}

		/// <summary>
		/// Creates a liner interpolated sample for every day in the the intervall. 
		/// </summary>
		/// <param name="mi">Intervall to extend.</param>
		public static IList<Sample> interpolateSamples(MeasurementIntervall mi)
		{
			List<Sample> list = new List<Sample>();

			int diffDays = mi.EndDate.DayOfYear - mi.StartDate.DayOfYear;

			//add first and inner samples
			for (int i = 0; i < diffDays; i++)
			{
				Sample interpol_Sample = 
					new Sample(
						mi.StartDate.AddDays((double)i),
						mi.mElectricEnergyStart + mi.ElectricityPerDay_kwh * i,
						mi.mGasStart + mi.GasPerDay_m3 * i,
						mi.mWaterStart + mi.WaterPerDay_m3 * i);
				
				list.Add(interpol_Sample);
			}

			////add last sample 
			//Sample last_Sample =
			//        new Sample(
			//            mi.EndDate,
			//            mi.mElectricEnergyEnd,
			//            mi.mGasEnd,
			//            mi.mWaterEnd);

			//list.Add(last_Sample);
			
			return list;
		}

		#endregion
	}
}
